#include<bits/stdc++.h> 
using namespace std;
//	一个二分搜索树指的是一棵有如下规则的二叉树：①左子树的所有结点的值都小于当前结点的值
//	②右子树所有结点的值都大于等于当前结点的值 ③左右子树都必须是二分搜索树
//	如果交换左子树和右子树的每个结点，则这个结果叫做二分搜索树的镜像。现在给定一系列的整
//	数值，我需要判断这是否是二分搜索树的前序遍历或二分搜索树镜像的前序遍历 
//1.每个输入都有一个测试用例，每个测试用例，第一行为一个正整数N≤1000，然后跟着N个整数值
//2.对于每个测试用例，首先输出一行YES或者NO来表示这个序列是否是先序遍历的BST或BST镜像。
//	如果是YES，下一行输出后序遍历的结果。
//3.二叉树，递归，分类讨论 
struct Node{
	int data;
	Node* left = NULL;	//左子结点 
	Node* right = NULL;	//右子结点 
	queue<Node*> leftQ;	//所有比当前结点小的放在左队列 
	queue<Node*> rightQ;	//大于等于的放在右队列 
};
int f = 0;	//判断当前属于是正在读入左还是右 
bool hasChange = false;	//左右交界处变换的那一次需要用这个来判断处理 
int type = 0;	//判断是镜像还是树本身 
int tt;
string ans = "";	//存储结果 
Node* build(Node* root){	//根据队列内容构建子树 
	f = tt;
	hasChange = false;
	if(!root->leftQ.empty()){	//如果左队列不为空，取左队列第一个为左子树根节点，然后剩余的按照大小放入该结点的左右队列，然后递归生成树 
		Node* leftroot = root->leftQ.front();
		root->leftQ.pop();
		while(!root->leftQ.empty()){
			Node* tmp = root->leftQ.front();
			root->leftQ.pop();
			if(f==-1 && tmp->data<leftroot->data){
				leftroot->leftQ.push(tmp);
			}
			else if(f==1 && tmp->data>=leftroot->data){
				leftroot->rightQ.push(tmp);
			}
			else if(hasChange==false){
				hasChange = true;
				if(tmp->data<leftroot->data){
					f=-1;
					leftroot->leftQ.push(tmp);
				}
				else{
					f = 1;
					leftroot->rightQ.push(tmp);
				}
			}
			else{
				cout<<"NO"<<endl;
				exit(0);
			}
		}
		leftroot = build(leftroot);
		root->left = leftroot;
	}
	f = tt;
	hasChange = false;
	if(!root->rightQ.empty()){	//同理生成右子树 
		Node* rightroot = root->rightQ.front();
		root->rightQ.pop();
		while(!root->rightQ.empty()){
			Node* tmp = root->rightQ.front();
			root->rightQ.pop();
			if(f==0){;
				if(tmp->data<rightroot->data){
					f = -1;
					rightroot->leftQ.push(tmp);
				}
				else{
					f = 1;
					rightroot->rightQ.push(tmp);
				}
			}
			else{
				if(f==-1 && tmp->data<rightroot->data){
					rightroot->leftQ.push(tmp);
				}
				else if(f==1 && tmp->data>=rightroot->data){
					rightroot->rightQ.push(tmp);
				}
				else if(hasChange==false){
					hasChange = true;
					if(tmp->data<rightroot->data){
						f=-1;
						rightroot->leftQ.push(tmp);
					}
					else{
						f = 1;
						rightroot->rightQ.push(tmp);
					}
				}
				else{
					cout<<"NO"<<endl;
					exit(0);
				}
			}
		}
		rightroot = build(rightroot);
		root->right = rightroot;
	}
	return root;
}
void post(Node* root){	//树的遍历输出 
	if(root->left!=NULL) post(root->left);
	if(root->right!=NULL) post(root->right);
	stringstream ss;
	ss<<root->data;
	ans += ss.str() + " ";
}
void post_mirror(Node* root){	//镜像的遍历输出 
	if(root->right!=NULL) post_mirror(root->right);
	if(root->left!=NULL) post_mirror(root->left);
	stringstream ss;
	ss<<root->data;
	ans += ss.str() + " ";			
}
int main(){
	int N;
	cin>>N;
	Node* root = new Node;	//先序遍历的第一个结点就是根结点 
	cin>>root->data;
	for(int i = 1;i<N;i++){
		int t;
		cin>>t;
		if(f==0){	//如果f=0表示还不知道是什么类型 
			Node* tmp = new Node;
			tmp->data = t;
			if(t<root->data){	//通过第二个结点的大小关系来判断当前序列表示的是树还是镜像 
				type = -1;	//树 
				f = -1;
				root->leftQ.push(tmp);
			}
			else{
				type = 1;	//镜像 
				f = 1;
				root->rightQ.push(tmp);
			}
		}
		else{
			if(f==-1 && t<root->data){	//当前正在遍历小的，且读入的这个也是小的 
				Node* tmp = new Node;
				tmp->data = t;
				root->leftQ.push(tmp);
			}
			else if(f==1 && t>=root->data){	//当前正在遍历大的，且读入的这个也是大的 
				Node* tmp = new Node;
				tmp->data = t;
				root->rightQ.push(tmp);
			}
			else if(hasChange==false){	//当前遍历的和读入的不一样，但是读入过程中还没有经历过大小的转换，则表示处在交界处 
				hasChange = true;
				Node* tmp = new Node;
				tmp->data = t; 
				if(t<root->data){
					f=-1;	//转变一下方向 
					root->leftQ.push(tmp);
				}
				else{
					f = 1;
					root->rightQ.push(tmp);
				}
			}
			else{	//否则就说明序列有问题，不是二分搜索树或者镜像 
				cout<<"NO"<<endl;
				return 0;
			}
		}
	}
	tt = type;
	root = build(root);
	cout<<"YES"<<endl;
	if(tt==-1) post(root);
	else post_mirror(root);
	cout<<ans.substr(0,ans.length()-1)<<endl;	//注意结尾空格 
	return 0;
}